import dayjs from 'dayjs';
import { Ref } from 'vue';
import useStore from '../store';
import { IScheduleResource } from '../interface';

/**
 * @description 根据事件源或拖拽元素样式计算排程数据
 * @export
 * @param {(DragEvent | MouseEvent)} event 事件源
 * @param {(Ref<HTMLCanvasElement | null>)} bodyCanvas 画布
 * @param {{ left: number; top: number; height?: number }} [dragStyle] 拖拽样式(有拖拽样式根据拖拽样式计算)
 * @param {string} [resourceId] 资源标识（有资源标识根据资源标识计算）
 * @returns {*}  {{
 *   startDate?: dayjs.Dayjs;
 *   endDate?: dayjs.Dayjs;
 *   resource?: IScheduleResource;
 *   position: { x: number; y: number };
 * }}
 */
export function calcScheduleByEvtOrDrag(
  event: DragEvent | MouseEvent,
  bodyCanvas: Ref<HTMLCanvasElement | null>,
  dragStyle?: { left: number; top: number; height?: number },
  resourceId?: string,
): {
  startDate?: dayjs.Dayjs;
  endDate?: dayjs.Dayjs;
  resource?: IScheduleResource;
  position: { x: number; y: number };
} {
  const { $uiCoordinate, $config, $renderLayer } = useStore();
  const {
    startTime,
    scaleRange,
    dragInterval,
    scaleColumnWidth,
    resourceColumnWidth,
    resourceBodyRowHeight,
  } = $config.getConfig();
  const { cellWidth } = $uiCoordinate;

  const resources = $renderLayer.getResources();

  const canvasRect = bodyCanvas.value!.getBoundingClientRect();

  // 计算鼠标在画布任务区的中的位置
  const x =
    event.clientX - canvasRect.left - scaleColumnWidth - resourceColumnWidth;
  const y = event.clientY - canvasRect.top;

  // 计算日期部分
  const dayIndex = Math.floor(x / cellWidth);

  const dayStart = dayjs(startTime)
    .add(dayIndex, 'day')
    .startOf('day')
    .hour(scaleRange[0]);

  // 计算资源部分
  let resourceIndex = Math.floor(y / resourceBodyRowHeight);

  if (resourceId) resourceIndex = resources.findIndex(r => r.id === resourceId);

  const resource = resources[resourceIndex];

  // 计算开始时间和结束时间
  let startDate: dayjs.Dayjs | undefined;
  let endDate: dayjs.Dayjs | undefined;

  if (x > 0) {
    const top: number = dragStyle?.top || y;

    const height: number | undefined = dragStyle?.height;

    // 计算时间部分
    const rangeHours = scaleRange[1] - scaleRange[0];
    const relativeTop = top - resourceIndex * resourceBodyRowHeight;
    const startHour = (relativeTop / resourceBodyRowHeight) * rangeHours;

    // 时间吸附计算
    const snapToInterval = (hour: number): number =>
      Math.round(hour / dragInterval) * dragInterval;
    const snappedStartHour = snapToInterval(startHour);
    startDate = dayStart.add(snappedStartHour, 'hour');
    // 有高度时计算结束时间
    if (height) {
      const endHour =
        ((relativeTop + height) / resourceBodyRowHeight) * rangeHours;
      const snappedEndHour = snapToInterval(endHour);
      endDate = dayStart.add(snappedEndHour, 'hour');
    }
  }
  return { resource, startDate, endDate, position: { x, y } };
}
